﻿using Microsoft.EntityFrameworkCore;
using MT.Common;
using MT.Common.EfExtenstion;
using MT.DAL.Abstract;
using MT.DAL.Abstract.UserCenter;
using MT.DAL.Cache.Users;
using MT.DAL.Dto.UserCenter;
using MT.Models.Entity;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Threading.Tasks;

namespace MT.DAL.Concrete.UserCenter
{
    public class UserService : BaseDbService, IUserService
    {
        private readonly UserDto _userDto;
        private readonly UserBusinessRoleDto _userBusinessRoleDto;
        private readonly UserRoleDto _userRoleDto;
        private readonly UserInstitutionDto _userInstitutionDto;
        private readonly UserCache _userCache;

        public UserService(IServiceConstructorParams serviceConstructorParams, AppDbContext dbContext) : base(serviceConstructorParams, dbContext)
        {
            _userDto = new UserDto(dbContext);
            _userBusinessRoleDto = new UserBusinessRoleDto(dbContext);
            _userRoleDto = new UserRoleDto(dbContext);
            _userInstitutionDto = new UserInstitutionDto(dbContext);
            _userCache = new UserCache(serviceConstructorParams, dbContext);
        }
        public async Task<List<UserRole>> GetUserRoleByUserIdAsync(int userId, int? institutionId)
        {
            Expression<Func<UserRole, bool>> filter = PredicateExtensionses.True<UserRole>();
            //-999 或者 null查询全部  如果是0 也默认查询

            filter = filter.And(s => s.UserId == userId);
            if (institutionId != null && institutionId >= 0)
            {
                filter = filter.And(f => f.InstitutionId == institutionId.Value);
            }

            var result = await _userRoleDto.GetListAsync<UserRole>(filter);
            return result.ToList();
        }
        /// <summary>
        /// 获取统一授权用户角色
        /// </summary>
        /// <param name="userId"></param>
        /// <param name="authRoleTypeDic"></param>
        /// <returns></returns>
        public async Task<UserRole> GetUserUnityRoleByUserIdAsync(int userId, string authRoleTypeDic)
        {
            Expression<Func<UserRole, bool>> filter = PredicateExtensionses.True<UserRole>();
            filter = filter.And(s => s.UserId == userId);
            filter = filter.And(f => f.AuthRoleTypeDic == authRoleTypeDic);
            return await _userRoleDto.GetAsync(filter);
        }
        public async Task<List<UserRole>> GetUserRoleByUserIdOrInstitutionIdsAsync(int userId, List<int> institutionIds)
        {
            Expression<Func<UserRole, bool>> filter = PredicateExtensionses.True<UserRole>();
            //-999 或者 null查询全部  如果是0 也默认查询
            filter = filter.And(s => s.UserId == userId);
            if (institutionIds != null)
            {
                filter = filter.And(f => institutionIds.Contains(f.InstitutionId.Value));
            }
            var result = await _userRoleDto.GetListAsync<UserRole>(filter);
            return result.ToList();
        }
        public async Task<User> GetByPhoneNumber(string phoneNumber)
        {
            var ids = await _userDto.GetScalarListAsync(x => x.PhoneNumber == phoneNumber && x.Delete == false, s => s.Id);
            var result = await GetCacheByIdsAsync(ids.ToList());
            return result == null ? null : result.FirstOrDefault();
        }
        public async Task<User> GetByUseName(string userName)
        {
            var ids = await _userDto.GetScalarListAsync(x => x.UserName == userName && x.Delete == false, s => s.Id);
            var result = await GetCacheByIdsAsync(ids.ToList());
            return result == null ? null : result.FirstOrDefault();
        }

        public async Task<User> GetByName(string name)
        {
            var ids = await _userDto.GetScalarListAsync(x => x.Name == name && x.Delete == false, s => s.Id);
            var result = await GetCacheByIdsAsync(ids.ToList());
            return result == null ? null : result.FirstOrDefault();
        }
        public async Task<User> GetByDingDingUnionidName(string dingDingUnionid)
        {
            var ids = await _userDto.GetScalarListAsync(x => x.DingDingUnionid == dingDingUnionid && x.Delete == false, s => s.Id);
            var result = await GetCacheByIdsAsync(ids.ToList());
            return result == null ? null : result.FirstOrDefault();
        }
        public async Task<User> GetUser(int userId)
        {
            ///var result = await GetByIdsAsync(new List<int>() { userId });
            ///return result.FirstOrDefault();
            return await _userDto.GetAsync(s => s.Id == userId && s.Delete == false);
        }
        public async Task<User> GetCacheUser(int userId)
        {
            var result = await GetCacheByIdsAsync(new List<int>() { userId });
            return result == null ? null : result.FirstOrDefault();
        }
        public async Task<User> GetUserByDingdingUserIdAsync(string dingdingUserId)
        {
            var result = await _userDto.GetListAsync<User>(x => x.DingDingUserId == dingdingUserId && x.Delete == false);
            return result == null ? null : result.FirstOrDefault();
        }
        public async Task<User> GetCacheUserByDingdingUserIdAsync(string dingdingUserId)
        {
            var ids = await _userDto.GetScalarListAsync(x => x.DingDingUserId == dingdingUserId && x.Delete == false, s => s.Id);
            var result = await GetCacheByIdsAsync(ids.ToList());
            return result == null ? null : result.FirstOrDefault();
        }

        public async Task<List<User>> GetCacheUserByPhoneListAsync(List<string> phones)
        {
            var ids = await _userDto.GetScalarListAsync(x => phones.Contains(x.PhoneNumber) && !string.IsNullOrEmpty(x.PhoneNumber) && x.Delete == false, s => s.Id);
            var result = await GetCacheByIdsAsync(ids.ToList());
            return result.ToList();
        }

        public async Task<List<User>> GetUserByPhoneListAsync(List<string> phones)
        {
            var result = await _userDto.GetListAsync<User>(x => phones.Contains(x.PhoneNumber) && !string.IsNullOrEmpty(x.PhoneNumber) && x.Delete == false);
            return result.ToList();
        }

        public async Task<List<User>> GetAppUserByPhoneListAsync(List<string> phones)
        {
            using (var conn =new  AppDbContext())
            {
                var result = conn.User.Where(x => phones.Contains(x.PhoneNumber) && !string.IsNullOrEmpty(x.PhoneNumber) && x.Delete == false);
                return await result.ToListAsync();
            }
               
           
        }
   
        public async Task<List<User>> GetCacheByIdsAsync(List<int> ids)
        {
            if (ids == null)
            {
                return null;
            }
            var notIds = await _userCache.ExistsToAsync(ids);
            if (notIds != null && notIds.Count > 0)
            {
                var result = await _userDto.GetListAsync<User>(x => notIds.Contains(x.Id) && x.Delete == false);
                await _userCache.AddAsync(result.ToList(), result.ToList().Select(s => s.Id).ToList());
            }
            return await _userCache.GetAsync(ids);
        }
        public async Task<List<User>> GetByIdsAsync(List<int> ids)
        {
            var result = await _userDto.GetListAsync<User>(x => ids.Contains(x.Id) && x.Delete == false);
            return result.ToList();
        }

        public async Task<PageModel<User>> GetPageAsync(int pageIndex, int pageSize, string name, int? institutionId)
        {
            return await _userDto.GetPageAsync(pageIndex, pageSize, name, institutionId);
        }
        public async Task<PageModel<User>> GetPageAsync(int pageIndex, int pageSize, string keyword, int? storeId = null, string businessRoleDic = null)
        {
            return await _userDto.GetPageAsync(pageIndex, pageSize, keyword, storeId, businessRoleDic);
        }
        public async Task<int> CreateAsync(User model)
        {
            return await _userDto.AddAsync(model);
        }
       
        public async Task<User> UpdateAsync(User model)
        {
            await _userDto.UpdateAsync(model);
            await _userCache.DelAsync(model.Id);
            return model;
        }
        public async Task<List<User>> UpdateRestAsync(List<User> list)
        {
            await _userDto.UpdateRestAsync(list);
            await _userCache.DelAsync(list.Select(s => s.Id).ToList());
            return list;
        }
        public async Task<List<User>> UpdateAsync(List<User> list)
        {
            await _userDto.UpdateAsync(list);
            await _userCache.DelAsync(list.Select(s => s.Id).ToList());
            return list;
        }
        public async Task<List<User>> UpdateAppAsync(List<User> list)
        {
            using (var context = new AppDbContext())
            {
                context.UpdateRange(list);
                await context.SaveChangesAsync();
            }
            await _userCache.DelAsync(list.Select(s => s.Id).ToList());
            return list;
        }
        public async Task<List<User>> UpdateAsync(List<User> list, List<string> fieldName)
        {
            await _userDto.UpdateAsync(list, fieldName);
            await _userCache.DelAsync(list.Select(s => s.Id).ToList());
            return list;
        }


        public async Task<User> UpdateByAsync(User model, List<int> ids, string[] modifiedProNames)
        {
            await _userDto.UpdateByAsync(model, s => ids.Contains(s.Id), modifiedProNames);
            await _userCache.DelAsync(ids);
            return model;
        }
        public async Task<List<UserBusinessRole>> GetUserBusinessRoleByUserIdAsync(int userId)
        {
            var result = await _userBusinessRoleDto.GetListAsync<UserBusinessRole>(s => s.UserId == userId);
            return result.ToList();
        }

        public async Task<int> GetCountByInstitutionIdAsync(int institutionId)
        {
            return await _userInstitutionDto.CoutAsync(s => s.InstitutionId == institutionId);
        }

        public Task<List<User>> GetUserByBusinessRoleAsync(int storeId, List<string> businessRoleDics)
        {
            throw new NotImplementedException();
        }
    }
}
